/*********************************************************************************************************
 *  ------------------------------------------------------------------------------------------------------
 *  file description
 *  ------------------------------------------------------------------------------------------------------
 *         \file  yaml.h
 *         \unit  yaml
 *        \brief  This is a C language version of yaml streamlined parser
 *       \author  Lamdonn
 *      \version  v0.1.0
 *      \license  GPL-2.0
 *    \copyright  Copyright (C) 2025 Lamdonn.
 ********************************************************************************************************/
#ifndef __yaml_H
#define __yaml_H

#ifdef __cplusplus
extern "C"
{
#endif

#include <stdarg.h>
#include <limits.h>
#include <stdlib.h>

/* version infomation */

#define YAML_V_MAJOR                        0
#define YAML_V_MINOR                        1
#define YAML_V_PATCH                        0

/* yaml type definition, hiding structural members, not for external use */

/**
 * \brief Opaque handle to YAML node structure
 * 
 * This typedef provides an opaque pointer to the internal YAML node structure.
 * The actual structure definition is hidden from external code to maintain encapsulation.
 */
typedef struct YAML* yaml_t;

/* yaml normal types define */

/**
 * \brief Enumeration of YAML data types
 * 
 * These constants represent the different data types supported by the YAML parser.
 * They are used to identify the type of value stored in a YAML node.
 */
#define YAML_TYPE_NULL                      (0) /* null type */
#define YAML_TYPE_BOOL                      (1) /* bool type */
#define YAML_TYPE_INT                       (2) /* number int type */
#define YAML_TYPE_FLOAT                     (3) /* number float type */
#define YAML_TYPE_STRING                    (4) /* string type */
#define YAML_TYPE_DATE                      (5) /* date type */
#define YAML_TYPE_SEQUENCE                  (6) /* sequence type */
#define YAML_TYPE_MAPPING                   (7) /* mapping type */
#define YAML_TYPE_DOCUMENT                  (8) /* document type */
#define YAML_TYPE_REFERENCE                 (9) /* reference type */
#define YAML_TYPE_COMPLEX_KEY               (10) /* complex key */

/* bool define */
/**
 * \brief Boolean values
 * 
 * These constants represent boolean true and false values in the YAML parser.
 */
#define YAML_FALSE                          (0) /* bool false */
#define YAML_TRUE                           (1) /* bool true */

/* error type define */
/**
 * \brief Error codes returned by the YAML parser
 * 
 * These constants represent various error conditions that can occur during YAML parsing.
 * They are used to indicate the nature of parsing errors to the calling code.
 */
#define YAML_E_OK                           (0) /* ok, no error */
#define YAML_E_INVALID                      (1) /* invalid, not a valid expected value */
#define YAML_E_END                          (2) /* many invalid characters appear at the end */
#define YAML_E_KEY                          (3) /* parsing key, invalid key content found */
#define YAML_E_VALUE                        (4) /* parsing value, invalid value content found */
#define YAML_E_MEMORY                       (5) /* memory allocation failed */
#define YAML_E_SQUARE                       (6) /* mising ']' */
#define YAML_E_CURLY                        (7) /* mising '}' */
#define YAML_E_TAB                          (8) /* incorrect indent depth */
#define YAML_E_MIX                          (9) /* mix type */
#define YAML_E_FLINE                        (10) /* the first line of value can only be a literal */
#define YAML_E_LNUMBER                      (11) /* the number exceeds the storage capacity */
#define YAML_E_LBREAK                       (12) /* line break */
#define YAML_E_NANCHOR                      (13) /* null anchor */
#define YAML_E_IANCHOR                      (14) /* invalid anchor */
#define YAML_E_RANCHOR                      (15) /* repeat anchor */
#define YAML_E_UANCHOR                      (16) /* undefine anchor */
#define YAML_E_TANCHOR                      (17) /* type error anchor */
#define YAML_E_DATE                         (18) /* date error */
#define YAML_E_TARTGET                      (19) /* target error */

/* dump flags define */
/**
 * \brief Flags used to control YAML dumping and loading behavior
 * 
 * These flags can be combined using bitwise OR to modify the behavior
 * of functions that dump or load YAML documents.
 */
#define YAML_F_NONE                         (0)    /* none flag */
#define YAML_F_DFLOW                        (0x01) /* dumps flow format */
#define YAML_F_LDOCS                        (0x02) /* load muti documents */
#define YAML_F_NOKEY                        (0x04) /* operate without key */
#define YAML_F_COMPLEX                      (0x08) /* operate with complex key */
#define YAML_F_ANCHOR                       (0x10) /* operate with anchor */
#define YAML_F_RECURSE                      (0x20) /* operate recurse */
#define YAML_F_REFERENCE                    (0x40) /* operate with reference */

/**
 * \brief Represents an invalid index value
 * 
 * This constant is used to indicate an invalid or non-existent index
 * in functions that operate on indexed YAML structures.
 */
#define YAML_INV_INDEX                      ((unsigned int)(-1))

// Functions for creating and deleting YAML nodes.
// These functions are used to initialize and free the memory resources of YAML nodes.

yaml_t yaml_create(void);
void yaml_delete(yaml_t yaml);

// Function for getting YAML parsing error information.
// It is used to obtain error line number and column number during YAML parsing.

int yaml_error_info(int* line, int* column);

// Functions for getting the type and size of a YAML node.
// Used to determine the data type of a YAML node and get the number of child elements of a container node.

int yaml_type(yaml_t yaml);
unsigned int yaml_size(yaml_t yaml);

// Functions for comparing and copying YAML nodes.
// Used to check if two YAML nodes are equal and to create a copy of a YAML node.

int yaml_compare(yaml_t yaml, yaml_t cmp, int flag);
yaml_t yaml_copy(yaml_t yaml, int flag);

// Functions for setting the key of a YAML node.
// Used to set a simple key or a complex key for a YAML node.

yaml_t yaml_set_key(yaml_t yaml, const char* key);
yaml_t yaml_set_key_complex(yaml_t yaml, yaml_t key);

// Functions for getting the key of a YAML node.
// Used to retrieve the simple key or complex key of a YAML node.

const char* yaml_key(yaml_t yaml);
yaml_t yaml_key_complex(yaml_t yaml);

// Functions for setting the value of a YAML node.
// Used to set a YAML node to different types of values such as null, boolean, integer, float, string, date, time, sequence, mapping, document, etc.

yaml_t yaml_set_null(yaml_t yaml);
yaml_t yaml_set_bool(yaml_t yaml, int b);
yaml_t yaml_set_int(yaml_t yaml, int num);
yaml_t yaml_set_float(yaml_t yaml, double num);
yaml_t yaml_set_string(yaml_t yaml, const char* string);
yaml_t yaml_set_date(yaml_t yaml, int year, char month, char day);
yaml_t yaml_set_time(yaml_t yaml, char hour, char minute, char second, int msec);
yaml_t yaml_set_utc(yaml_t yaml, char hour, char minute);
yaml_t yaml_set_sequence(yaml_t yaml, yaml_t sequence);
yaml_t yaml_set_mapping(yaml_t yaml, yaml_t mapping);
yaml_t yaml_set_document(yaml_t yaml, yaml_t document);

// Functions for getting the value of a YAML node.
// Used to retrieve the boolean value, integer value, float value, string value, sequence value, mapping value, document value, etc. of a YAML node.

int yaml_value_bool(yaml_t yaml);
int yaml_value_int(yaml_t yaml);
double yaml_value_float(yaml_t yaml);
const char* yaml_value_string(yaml_t yaml);
yaml_t yaml_value_sequence(yaml_t yaml);
yaml_t yaml_value_mapping(yaml_t yaml);
yaml_t yaml_value_document(yaml_t yaml);

// Functions for attaching and detaching YAML nodes.
// Used to attach a YAML node to another node or detach a child node from a node.

yaml_t yaml_attach(yaml_t yaml, unsigned int index, yaml_t attach);
yaml_t yaml_dettach(yaml_t yaml, unsigned int index);

// Functions for inserting values into a YAML node.
// Used to insert different types of values such as null, boolean, integer, float, string, sequence, mapping, document, reference, etc. into a YAML node.

yaml_t yaml_insert_null(yaml_t yaml, const char* key, unsigned int index);
yaml_t yaml_insert_bool(yaml_t yaml, const char* key, unsigned int index, int b);
yaml_t yaml_insert_int(yaml_t yaml, const char* key, unsigned int index, int num);
yaml_t yaml_insert_float(yaml_t yaml, const char* key, unsigned int index, double num);
yaml_t yaml_insert_string(yaml_t yaml, const char* key, unsigned int index, const char* string);
yaml_t yaml_insert_sequence(yaml_t yaml, const char* key, unsigned int index, yaml_t sequence);
yaml_t yaml_insert_mapping(yaml_t yaml, const char* key, unsigned int index, yaml_t mapping);
yaml_t yaml_insert_document(yaml_t yaml, unsigned int index, yaml_t document);
yaml_t yaml_insert_reference(yaml_t yaml, const char* key, unsigned int index, const char* anchor, yaml_t doc);

// Function for removing a value from a YAML node.
// Used to remove a value from a YAML node according to the key and index.

int yaml_remove(yaml_t yaml, const char* key, unsigned int index);

// Functions for getting the index of a YAML node.
// Used to obtain the index of a value in a YAML node, supporting the index acquisition of simple keys and complex keys.

unsigned int yaml_get_index(yaml_t yaml, const char* key, unsigned int index);
unsigned int yaml_get_index_complex(yaml_t yaml, yaml_t key);

// Functions for getting child nodes of a YAML node.
// Used to get the child nodes of a YAML node according to the key and index, supporting the retrieval of child nodes of simple keys and complex keys.

yaml_t yaml_get_child(yaml_t yaml, const char* key, unsigned int index);
yaml_t yaml_get_child_complex(yaml_t yaml, yaml_t key);

// Functions for setting and getting the alias of a YAML node.
// Used to set an alias for a YAML node and retrieve the alias of a YAML node.

yaml_t yaml_set_alias(yaml_t yaml, const char* alias, yaml_t doc);
const char* yaml_get_alias(yaml_t yaml);

// Functions for setting and getting the anchor of a YAML node.
// Used to set an anchor for a YAML node, retrieve the anchor, and get the size of the anchor.

yaml_t yaml_set_anchor(yaml_t yaml, const char* anchor, yaml_t doc);
yaml_t yaml_get_anchor(yaml_t yaml, unsigned int index);
unsigned int yaml_anchor_size(yaml_t yaml);

// YAML serialization functions.
// Used to serialize a YAML node into a string (yaml_dumps) or write it to a file (yaml_file_dump).

char* yaml_dumps(yaml_t yaml, int preset, int* len, int flag);
int yaml_file_dump(yaml_t yaml, char* filename);

// YAML deserialization functions.
// Used to load YAML data from a string (yaml_loads) or a file (yaml_file_dump) and construct a YAML node.

yaml_t yaml_loads(const char* text, int flag);
yaml_t yaml_file_load(char* filename, int flag);

// Macros for judging the type of a YAML node.
// Used to determine whether a YAML node is of a specific type (null, bool, int, float, string, sequence, mapping, document).

#define yaml_isnull(yaml)                           (yaml_type(yaml)==YAML_TYPE_NULL)
#define yaml_isbool(yaml)                           (yaml_type(yaml)==YAML_TYPE_BOOL)
#define yaml_isint(yaml)                            (yaml_type(yaml)==YAML_TYPE_INT)
#define yaml_isfloat(yaml)                          (yaml_type(yaml)==YAML_TYPE_FLOAT)
#define yaml_isstring(yaml)                         (yaml_type(yaml)==YAML_TYPE_STRING)
#define yaml_issequence(yaml)                       (yaml_type(yaml)==YAML_TYPE_SEQUENCE)
#define yaml_ismapping(yaml)                        (yaml_type(yaml)==YAML_TYPE_MAPPING)
#define yaml_isdocument(yaml)                       (yaml_type(yaml)==YAML_TYPE_DOCUMENT)

// Macros for adding values to a YAML node.
// Used to quickly add different types of values to a YAML sequence or mapping node.

#define yaml_seq_add_null(yaml)                     yaml_insert_null((yaml), 0, yaml_size((yaml)))
#define yaml_seq_add_bool(yaml, b)                  yaml_insert_bool((yaml), 0, yaml_size((yaml)), (b))
#define yaml_seq_add_int(yaml, num)                 yaml_insert_int((yaml), 0, yaml_size((yaml)), (num))
#define yaml_seq_add_float(yaml, num)               yaml_insert_float((yaml), 0, yaml_size((yaml)), (num))
#define yaml_seq_add_string(yaml, string)           yaml_insert_string((yaml), 0, yaml_size((yaml)), (string))
#define yaml_seq_add_sequence(yaml, sequence)       yaml_insert_sequence((yaml), 0, yaml_size((yaml)), (sequence))
#define yaml_seq_add_mapping(yaml, mapping)         yaml_insert_mapping((yaml), 0, yaml_size((yaml)), (mapping))
#define yaml_map_add_null(yaml, key)                yaml_insert_null((yaml), (key), yaml_size((yaml)))
#define yaml_map_add_bool(yaml, key, b)             yaml_insert_bool((yaml), (key), yaml_size((yaml)), (b))
#define yaml_map_add_int(yaml, key, num)            yaml_insert_int((yaml), (key), yaml_size((yaml)), (num))
#define yaml_map_add_float(yaml, key, num)          yaml_insert_float((yaml), (key), yaml_size((yaml)), (num))
#define yaml_map_add_string(yaml, key, string)      yaml_insert_string((yaml), (key), yaml_size((yaml)), (string))
#define yaml_map_add_sequence(yaml, key, sequence)  yaml_insert_sequence((yaml), (key), yaml_size((yaml)), (sequence))
#define yaml_map_add_mapping(yaml, key, mapping)    yaml_insert_mapping((yaml), (key), yaml_size((yaml)), (mapping))

#ifdef __cplusplus
}
#endif

#endif
